/************************************************************************
 * @file	Application.hpp
 * @brief	Manage base application
 *
 ************************************************************************/

#ifndef __APPLICATION_HPP__
#define __APPLICATION_HPP__

#include "../event/EventManager.hpp"
#include "../event/EventBase.hpp"

#include <boost/thread.hpp>

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

namespace irr
{
    class IrrlichtDevice;
    namespace video
    {
        class IVideoDriver;
    }
    namespace scene
    {
        class ISceneManager;
    }
    namespace gui
    {
        class IGUIEnvironment;
    }
}

namespace core
{
    class Application
    {
    public:

        //Constructor / Destructor ///////////////////////////////////////////

        /**
         * @fn		Application()
         * @brief	Constructor
         */
        Application();

        /**
         * @fn		~Application()
         * @brief	Virtual Destructor
         */
        virtual ~Application();

        /**
         * @fn			go()
         * @brief		Entry function of the program
         */
        virtual void go();

		static Application* getCurrentApplication()
		{
			return m_currentApplication;
		}

        inline irr::IrrlichtDevice *        getIrrlichtDevice()         {   return m_device;    }
        inline irr::video::IVideoDriver *   getIrrlichtVideoDriver()    {   return m_driver;    }
        inline irr::scene::ISceneManager *  getIrrlichtSceneManager()   {   return m_sceneManager;  }
        inline irr::gui::IGUIEnvironment *  getIrrlichtGUIEnvironment() {   return m_guiEnv;    }

    protected:
        //Init / Destroy //////////////////////////////////////////////////////

        /**
         * @fn			init()
         * @brief		Initialise the application (Ogre, GUI, Manager, ...)
         * @return		true if the initialisation succeed, otherwise false
         */
        virtual bool init();

        /**
         * @fn			destroy()
         * @brief		Destroy the application (Ogre, GUI, Manager, ...)
         * @return		true if the destroy succeed, otherwise false
         */
        virtual bool destroy();

        /**
         * @fn			onReceiveWindowQuit(boost::shared_ptr<Event::EventBase> _evt)
         * @brief		quit the application
         * @param           _evt        the event
         */
        virtual void onReceiveQuitApplication(boost::shared_ptr<Event::EventBase> _evt);

        /**
         * @fn			initialiseIrrlicht()
         * @brief		Initialise Irrlicht and window
         * @return		true if the initialisation succeed, otherwise false
         */
        virtual bool initialiseIrrlicht();

        /**
         * @fn			initialiseManagers()
         * @brief		Initialise all Managers
         * @return		true if the initialisation succeed, otherwise false
         */
        virtual bool initialiseManagers();

        /**
         * @fn			initialiseScene()
         * @brief		Initialise the Scene
         * @return		true if the initialisation succeed, otherwise false
         */
        virtual bool initialiseScene();

        /**
         * @fn			destroyManagers()
         * @brief		Destroy all Managers
         * @return		true if the destroy succeed, otherwise false
         */
        virtual bool destroyManagers();

        //SystemUpdate ////////////////////////////////////////////////////////

        /**
         * @fn			update(float _time)
         * @brief		Update
         */
        virtual void update(float _time);

        /**
         * @fn			updateManagers(float _time)
         * @brief		Update all managers
         */
        virtual void updateManagers(float _time);

        //Members /////////////////////////////////////////////////////////////

        std::wstring m_windowName;
        bool m_continue; /// Continue the rendering or not

        irr::IrrlichtDevice * m_device;
        irr::video::IVideoDriver * m_driver;
	    irr::scene::ISceneManager * m_sceneManager;
        irr::gui::IGUIEnvironment* m_guiEnv;

		static Application * m_currentApplication;
    };

} // namespace core



#endif //__APPLICATION_HPP__